﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Resources;
using _Font = System.Drawing.Font;
using GDI = System.Drawing;

namespace WpfCallScreen.Common
{
    public class CruveWriteableBitmap : FrameworkElement
    {
        private static PrivateFontCollection pfc = new PrivateFontCollection();
        private WriteableBitmap bitmap;

        private int bitmap_width = 0;
        private int bitmap_height = 0;

        private static _Font font = null;
        private static _Font time_font = null;

        private PointF[][] horizontals = null;
        private PointF[][] horizontals_thin = null;
        private PointF[][] verticals = null;
        private PointF[][] verticals_thin = null;

        private List<PointF> top_points1;
        private List<PointF> top_points2;
        private List<PointF> top_points3;
        private List<PointF> bottom_points;

        private List<PointF> labelPosition_up;
        private List<string> labelText_up;
        private List<PointF> labelPosition_down;
        private List<string> labelText_down;

        private List<PointF> timePosition;
        private List<string> timeText;

        private GDI.Pen blackPen = new GDI.Pen(GDI.Color.Black, 1.5f);
        private GDI.Pen grayPen = new GDI.Pen(GDI.Color.Gray, 1f);

        private GDI.Pen top_pen1 = new GDI.Pen(GDI.Color.Black, 2);
        private GDI.Pen top_pen2 = new GDI.Pen(GDI.Color.Orange, 2);
        private GDI.Pen top_pen3 = new GDI.Pen(GDI.Color.Purple, 2); public float scaleX { get; set; } = 1f;
        private float _ScaleY { get; set; } = 1f;
        public float ScaleY
        {
            get { return _ScaleY; }
            set
            {
                _ScaleY = value;
            }
        }

        static CruveWriteableBitmap()
        {
            //var appRootDataDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "msyh.ttf");
            //if (!File.Exists(appRootDataDir))
            //{
            //    var key = $"/CurveChartDemo;component/Fonts/msyh.ttf";
            //    StreamResourceInfo info = Application.GetResourceStream(new Uri(key, UriKind.Relative));
            //    using (var stream = info.Stream)
            //    {
            //        byte[] bytes = new byte[stream.Length];
            //        int len = stream.Read(bytes, 0, bytes.Length);
            //        File.WriteAllBytes(appRootDataDir, bytes);
            //    }
            //}
            //pfc.AddFontFile(appRootDataDir);
        }

        public CruveWriteableBitmap()
        {
            //time_font = new _Font(pfc.Families[0], 10);
            //font = new _Font(pfc.Families[0], 8);
            time_font = new _Font("宋体", 10);
            font = new _Font("宋体", 8);
        }

        public void DrawPoints()
        {
            //InitBitmap();
            if (this.bitmap == null)
            {
                return;
            }

            this.bitmap.Lock();
            using (Bitmap backBufferBitmap = new Bitmap(this.bitmap_width, this.bitmap_height,
                this.bitmap.BackBufferStride, GDI.Imaging.PixelFormat.Format24bppRgb,
                this.bitmap.BackBuffer))
            {
                using (Graphics backBufferGraphics = Graphics.FromImage(backBufferBitmap))
                {
                    backBufferGraphics.SmoothingMode = SmoothingMode.AntiAlias;
                    backBufferGraphics.CompositingQuality = CompositingQuality.HighSpeed;

                    backBufferGraphics.Clear(GDI.Color.White);

                    //粗横线
                    if (this.horizontals != null)
                    {
                        foreach (var horizontal in this.horizontals)
                        {
                            backBufferGraphics.DrawLine(blackPen, horizontal[0], horizontal[1]);
                        }
                    }
                    //细横线
                    if (this.horizontals_thin != null)
                    {
                        foreach (var horizontal in this.horizontals_thin)
                        {
                            backBufferGraphics.DrawLine(grayPen, horizontal[0], horizontal[1]);
                        }
                    }
                    //粗竖线
                    if (this.verticals != null)
                    {
                        foreach (var vertical in this.verticals)
                        {
                            backBufferGraphics.DrawLine(blackPen, vertical[0], vertical[1]);
                        }
                    }
                    //细竖线
                    if (this.verticals_thin != null)
                    {
                        foreach (var vertical in this.verticals_thin)
                        {
                            backBufferGraphics.DrawLine(grayPen, vertical[0], vertical[1]);
                        }
                    }
                    //上图曲线1
                    if (this.top_points1 != null && this.top_points1.Count > 0)
                    {
                        backBufferGraphics.DrawLines(top_pen1, top_points1.ToArray());
                    }
                    //上图曲线2
                    if (this.top_points2 != null && this.top_points2.Count > 0)
                    {
                        backBufferGraphics.DrawLines(top_pen2, this.top_points2.ToArray());
                    }
                    //上图曲线3
                    if (this.top_points3 != null && this.top_points3.Count > 0)
                    {
                        backBufferGraphics.DrawLines(top_pen3, this.top_points3.ToArray());
                    }
                    //下图曲线
                    if (this.bottom_points != null && this.bottom_points.Count > 0)
                    {
                        backBufferGraphics.DrawLines(top_pen1, this.bottom_points.ToArray());
                    }

                    //文本
                    if (labelPosition_up != null && labelPosition_up.Count > 0)
                    {
                        SizeF fontSize = backBufferGraphics.MeasureString(labelText_up[0], font);
                        for (int i = 0; i < labelPosition_up.Count; ++i)
                        {
                            backBufferGraphics.DrawString(labelText_up[i], font, GDI.Brushes.Black, labelPosition_up[i].X, labelPosition_up[i].Y - fontSize.Height);
                        }
                    }
                    if (labelPosition_down != null && labelPosition_down.Count > 0)
                    {
                        for (int i = 0; i < labelPosition_down.Count; ++i)
                        {
                            backBufferGraphics.DrawString(labelText_down[i], font, GDI.Brushes.Black, labelPosition_down[i].X, labelPosition_down[i].Y);
                        }
                    }
                    if (timePosition != null && timePosition.Count > 0)
                    {
                        for (int i = 0; i < timePosition.Count; ++i)
                        {
                            if (i == 0)
                                backBufferGraphics.DrawString(timeText[i], time_font, GDI.Brushes.Black, timePosition[i].X, timePosition[i].Y);
                            else
                            {
                                SizeF fontSize = backBufferGraphics.MeasureString(timeText[i], time_font);
                                backBufferGraphics.DrawString(timeText[i], time_font, GDI.Brushes.Black, timePosition[i].X - fontSize.Width / 2, timePosition[i].Y);
                            }

                        }
                    }

                    backBufferGraphics.Flush();
                }
            }
            this.bitmap.AddDirtyRect(new Int32Rect(0, 0, this.bitmap_width, this.bitmap_height));
            this.bitmap.Unlock();
        }
        public void UpdateTimeLabel(List<PointF> timePosition, List<string> timeText)
        {
            this.timePosition = timePosition;
            this.timeText = timeText;
        }
        public void UpdatePosition(List<PointF> fhr1_points, List<PointF> fhr2_points, List<PointF> fhr3_points, List<PointF> toco_points)
        {
            this.top_points1 = fhr1_points;
            this.top_points2 = fhr2_points;
            this.top_points3 = fhr3_points;
            this.bottom_points = toco_points;
        }

        public void UpdateLabelPosition(List<PointF> labelPosition_up, List<string> labelText_up, List<PointF> labelPosition_down, List<string> labelText_down)
        {
            this.labelPosition_up = labelPosition_up;
            this.labelText_up = labelText_up;
            this.labelPosition_down = labelPosition_down;
            this.labelText_down = labelText_down;
        }

        public void UpdateHorizontalLine(PointF[][] horizontals, PointF[][] horizontals_thin)
        {
            this.horizontals = horizontals;
            this.horizontals_thin = horizontals_thin;
        }

        public void UpdateVerticalLine(PointF[][] verticals, PointF[][] verticals_thin)
        {
            this.verticals = verticals;
            this.verticals_thin = verticals_thin;
        }

        protected override void OnRender(DrawingContext dc)
        {
            InitBitmap();
            if (this.bitmap != null)
            {
                dc.DrawImage(bitmap, new Rect(0, 0, RenderSize.Width, RenderSize.Height));
            }
            base.OnRender(dc);
        }

        private void InitBitmap()
        {
            if (bitmap == null || this.bitmap.Width != (int)this.ActualWidth || this.bitmap.Height != (int)this.ActualHeight)
            {
                if ((int)this.ActualWidth > 0 && (int)this.ActualHeight > 0)
                {
                    this.bitmap_width = (int)this.ActualWidth;
                    this.bitmap_height = (int)this.ActualHeight;
                    this.bitmap = new WriteableBitmap(bitmap_width, bitmap_height, 96, 96, PixelFormats.Bgr24, null);
                    this.bitmap.Lock();
                    using (Bitmap backBufferBitmap = new Bitmap(bitmap_width, bitmap_height,
                        this.bitmap.BackBufferStride, GDI.Imaging.PixelFormat.Format24bppRgb,
                        this.bitmap.BackBuffer))
                    {
                        using (Graphics backBufferGraphics = Graphics.FromImage(backBufferBitmap))
                        {
                            backBufferGraphics.SmoothingMode = SmoothingMode.HighSpeed;
                            backBufferGraphics.CompositingQuality = CompositingQuality.HighSpeed;
                            backBufferGraphics.Clear(GDI.Color.White);
                            backBufferGraphics.Flush();
                        }
                    }
                    this.bitmap.AddDirtyRect(new Int32Rect(0, 0, bitmap_width, bitmap_height));
                    this.bitmap.Unlock();
                }
            }
        }
    }
}